#include "PropExtractorViewer.h"

#include <QTreeWidgetItem>

#include <QtGui/QMessageBox>
#include <QByteArray>
#include <QFile>
#include <QDir>
#include <QMenu>
#include <QFileInfoList>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QFileDialog>
#include <QResizeEvent>

void QStringToWChar(wchar_t** a_Dst, QString& a_Src)
{
	*a_Dst = new wchar_t[a_Src.length() + 1];
	memset(*a_Dst, 0, (a_Src.length() + 1) * sizeof(wchar_t));
	a_Src.toWCharArray(*a_Dst);
}

PropExtractorViewer* PropExtractorViewer::s_Instance = NULL;

PropExtractorViewer& PropExtractorViewer::Get()
{
	if (!s_Instance) { s_Instance = new PropExtractorViewer; }
	return *s_Instance;
}

PropExtractorViewer::PropExtractorViewer(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags)
{
	pe::PELogOpen();
	pe::PropExtractor::Get().InitLoader("AliceSoft");

	ui.setupUi(this);

	m_WidgetTree = this->findChild<WidgetTree*>("treFolder");
	m_WidgetImage = this->findChild<WidgetImage*>("wdgImage");

	// menu

	m_MenuRecent = findChild<QMenu*>("menuFile");
	m_MenuRecent->addSeparator();

	QList<QAction*> menu_list = m_MenuRecent->actions();
	for (QList<QAction*>::iterator it = menu_list.begin(); it != menu_list.end(); it++)
	{
		m_ListMenuActions.push_back(*it);
	}
}

PropExtractorViewer::~PropExtractorViewer()
{

}

void PropExtractorViewer::ParseCommandArguments(QStringList& a_List)
{
	// get working directory

	wchar_t dir[_MAX_PATH];
	GetModuleFileNameW(NULL, dir, _MAX_PATH);
	wchar_t* lastslash = wcsrchr(dir, '\\');
	wchar_t workingdir[_MAX_PATH];
	wcsncpy(workingdir, dir, lastslash - dir + 1);
	workingdir[lastslash - dir + 1] = 0;
	m_WorkingDir = QString::fromWCharArray(workingdir);

	// recent paths

	if (QFile::exists(m_WorkingDir + "paths.ini"))
	{
		QFile* read = new QFile(m_WorkingDir + "paths.ini");
		read->open(QIODevice::ReadOnly | QIODevice::Text);

		while (!read->atEnd()) 
		{
			QString line = QString::fromUtf8(read->readLine());
			AddRecentPath(line);
		}

		read->close();
	}

	// load files from command line

	for (QStringList::iterator it = a_List.begin() + 1; it != a_List.end(); it++)
	{
		LoadFromPath((*it));
	}
}

// ================================
// Slots
// ================================

void PropExtractorViewer::on_btnBrowse_pressed()
{
	LoadFromArchiveDialog();
}

void PropExtractorViewer::on_treFolder_itemClicked(QTreeWidgetItem* a_Item, int a_Column)
{
	UpdateTree(a_Item);
}

void PropExtractorViewer::on_treFolder_itemSelectionChanged()
{
	if (m_WidgetTree->selectedItems().size() > 0)
	{
		UpdateTree(m_WidgetTree->selectedItems()[0]);
	}
}

void PropExtractorViewer::on_actLoadFromDirectory_triggered(bool a_Checked /*= false*/)
{
	QString dir = QFileDialog::getExistingDirectory(this, "Select a directory", "", QFileDialog::ShowDirsOnly);
	LoadFromPath(dir);
}

void PropExtractorViewer::on_actLoadFromArchive_triggered(bool a_Checked /*= false*/)
{
	LoadFromArchiveDialog();
}

// ================================
// Events
// ================================

void PropExtractorViewer::resizeEvent(QResizeEvent* a_Event)
{
	QSize newsize = a_Event->size();
}

void PropExtractorViewer::closeEvent(QCloseEvent* a_Event)
{
	WriteRecentPaths();
}

// ================================
// Functions
// ================================

void PropExtractorViewer::UpdateTree(QTreeWidgetItem* a_Item, int a_Column)
{
	pe::PEImageRaw raw;
	if (m_WidgetTree->GetSelectedImage(raw))
	{
		m_WidgetImage->Load(&raw);
		PEImageRawDelete(&raw);

		return;
	}

	m_WidgetImage->Clear();
}

void PropExtractorViewer::LoadFromPath(QString a_File)
{
	QFileInfo found(a_File);
	if (!found.exists())
	{
		QMessageBox::warning(this, "Warning!", "Path does not exist or is not available.");
		return;
	}

	if (found.isDir())
	{
		QString dir = found.canonicalFilePath();

		QLineEdit* wdg_path = findChild<QLineEdit*>("inpPath");
		wdg_path->setText(dir);

		m_WidgetTree->LoadFromDir(dir, false);
		AddRecentPath(dir);
	}
	else if (found.isFile())
	{
		QLineEdit* wdg_path = findChild<QLineEdit*>("inpPath");
		wdg_path->setText(found.absoluteFilePath());

		QString final = found.absoluteFilePath();
		AddRecentPath(final);
		m_WidgetTree->LoadFromZip(final, false);
	}
}

void PropExtractorViewer::LoadRecentFile()
{
	QAction* act = (QAction*)sender();
	LoadFromPath(act->text());
}

void PropExtractorViewer::AddRecentPath(QString a_Path)
{
	QString path = a_Path.trimmed();

	bool found = false;
	for (QStringList::iterator it = m_ListRecentPaths.begin(); it != m_ListRecentPaths.end(); it++)
	{
		if ((*it) == path)
		{
			found = true;
			break;
		}
	}

	if (!found)
	{
		m_ListRecentPaths.push_back(path);

		for (QList<QAction*>::iterator it = m_ListRecentActions.begin(); it != m_ListRecentActions.end(); it++)
		{
			delete (*it);
		}
		m_ListRecentActions.clear();

		for (int i = m_ListRecentPaths.size() - 1; i >= 0; i--)
		{
			QAction* latest = m_MenuRecent->addAction(m_ListRecentPaths[i]);
			connect(latest, SIGNAL(triggered()), this, SLOT(LoadRecentFile()));
			m_ListRecentActions.push_front(latest);
		}
	}
}

void PropExtractorViewer::WriteRecentPaths()
{
	QFile* write = new QFile(m_WorkingDir + "paths.ini");
	write->open(QIODevice::WriteOnly | QIODevice::Truncate);

	for (QStringList::iterator it = m_ListRecentPaths.begin(); it != m_ListRecentPaths.end(); it++)
	{
		write->write((*it).toUtf8());
		write->write("\n");
	}

	write->close();
}

void PropExtractorViewer::LoadFromArchiveDialog()
{
	QString path = QFileDialog::getOpenFileName(this, "Select an archive", QDir::currentPath(), "Archives (*.red *.afa *.ald)");
	LoadFromPath(path);
}

bool PropExtractorViewer::IsSafeMode()
{
	QCheckBox* wdg_safemode = findChild<QCheckBox*>("chkSafeMode");
	return wdg_safemode->isChecked();
}
